using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;

using Gtk;
using Mono.Cecil;
using MonoDevelop.Components.Commands;
using MonoDevelop.Core;
using MonoDevelop.Core.Gui.Dialogs;
using MonoDevelop.Projects;
using MonoDevelop.Projects.CodeGeneration;
using MonoDevelop.Projects.Parser;
using MonoDevelop.Projects.Text;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Gui.Pads;
using MonoDevelop.Ide.Gui.Content;
using MonoDevelop.Ide.Tasks;


namespace MonoDevelop.SmokeyAddin
{
        internal static class SmokeyRunner
        {
                public static List<Violation> Inspect (string fileName)
                {
                        string pathToSmokey = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().CodeBase)
                                                + Path.DirectorySeparatorChar + "smokey.exe";
                        string arguments = "-xml";
                        if (SmokeyConfiguration.ExcludeNameEnabled)
                                arguments += " -exclude-name:" + SmokeyConfiguration.ExcludedName;
                        ProcessStartInfo startInfo = new ProcessStartInfo ("mono");
                        // we have to specify 2.0 runtime explicitly because otherwise it may want to load 1.1 (mono bug?)
                        startInfo.Arguments = string.Format ("--runtime=v2.0.50727 {0} {1} {2}",
                                                                pathToSmokey, arguments, fileName);
                        startInfo.RedirectStandardOutput = true;
                        startInfo.UseShellExecute = false;
                        Process smokey = null;
                        string output = string.Empty;
                        try {
                                smokey = Process.Start (startInfo);
                                output = smokey.StandardOutput.ReadToEnd ();
                                // TODO: in future, it'd be better to read it with xml reader on the fly
                        } catch (Exception ex) {
                                throw new CouldNotRunSmokeyException (ex);
                        } finally {
                                if (smokey != null) smokey.Dispose ();
                        }
                        return SmokeyRunner.ParseViolationList (output);
                }
                
                private static List<Violation> ParseViolationList (string xml)
                {
                        XmlDocument document = new XmlDocument ();
                        try {
                                document.LoadXml (xml);
                                string selectErrors = "/Errors/Error";
                                List<Violation> violations = new List<Violation> ();
                                foreach (XmlNode node in document.SelectNodes (selectErrors))
                                        violations.Add (ViolationParser.Parse (node));
                                return violations;
                        } catch (Exception ex) {
                                throw new CouldNotParseSmokeyOutputException (ex);
                        }
                }
        }
}
